Skip to content

feat: Dashboard enterprise-grade organization with drag-and-drop#1972

Open
alex-fedotyev wants to merge 7 commits intomainfrom
feat/dashboard-dnd-organization
Open

feat: Dashboard enterprise-grade organization with drag-and-drop#1972
alex-fedotyev wants to merge 7 commits intomainfrom
feat/dashboard-dnd-organization

Conversation

@alex-fedotyev
Copy link
Contributor

@alex-fedotyev alex-fedotyev commented Mar 23, 2026

Summary

Implements the remaining features from #1929: drag-and-drop tile organization, section reordering, tab and group container types, and UX polish.

Builds on #1926 (authoring UX + DashboardContainer abstraction).

Changes by commit

  1. feat: Extend DashboardContainer schema for tab and group types

    • Adds 'tab' and 'group' to the container type enum
    • Adds activeTabId for tab state, parentId for child tab containers
  2. feat: Add @dnd-kit drag-and-drop infrastructure for dashboards

    • @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities
    • DashboardDndContext.tsx: provider, drag handles, drop zones, sortable wrappers
    • pointerWithin collision detection for correct cross-section targeting
  3. feat: Add GroupContainer and TabContainer components

    • GroupContainer: bordered, always-visible, drag handle, inline rename
    • TabContainer: multi-tab bar with add (+), rename (double-click), remove (x), tab switching
  4. feat: Add drag handle to SectionHeader, fix theme-aware borders

    • Grip icon on hover, var(--mantine-color-default-border) for light/dark themes
  5. feat: Integrate DnD, container types, and polish into dashboard page

    • Cross-section tile drag, section reorder, container type rendering
    • Delete confirmation dialog, empty placeholders, select-and-group (Shift+click → Cmd+G)
  6. test: Add tests for container types, reordering, and grouping — 14 new tests

  7. feat: Implement multi-tab container support

    • parentId on containers links child tabs to parent tab set
    • Auto-creates initial tab on tab container creation
    • Add/rename/delete tabs, active tab tracking, tile migration on tab delete
    • Render-prop pattern: only active tab's tiles visible

Verified via Playwright MCP on Vercel preview

Feature Result
Drag tile Section → Group ✅ containerId updated
Drag tile Group → Section ✅ reverse works
Section reorder C→A ✅ order changed A,B,C → C,A,B
Shift+click selection ✅ blue outlines + "2 tiles selected" bar
Cmd+G group ✅ creates section, assigns tiles
Delete confirmation ✅ shows name + tile count
Empty placeholders ✅ dashed border + hint
Group container ✅ bordered, drag handle, inline rename
Multi-tab container 🔄 CI passes, Vercel testing pending

Test plan

  • 39 unit tests pass (25 existing + 14 new)
  • 691 common-utils tests pass
  • All app unit tests pass
  • All 4 E2E test shards pass (91 tests)
  • ESLint clean, no TypeScript errors
  • Backward compatible

Closes #1929

@changeset-bot
Copy link

changeset-bot bot commented Mar 23, 2026

⚠️ No Changeset found

Latest commit: 7815b5e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Mar 24, 2026 3:22am

Request Review

@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

Knip - Unused Code Analysis

0 change in total issues (240 on main → 240 on PR)

Category main PR Diff
Unused files 9 9 0
Unused dependencies 14 14 0
Unused devDependencies 20 20 0
Unlisted dependencies 14 14 0
Unresolved imports 2 2 0
Unlisted binaries 2 2 0
Unused exports 132 132 0
Unused exported types 41 41 0
Unused enum members 2 2 0
Duplicate exports 4 4 0
What is this?

Knip finds unused files, dependencies, and exports in your codebase.
This comment compares the PR branch against main to detect regressions.

Run yarn knip locally to see full details.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

PR Review

  • ⚠️ ActionIcon variant="subtle" in GroupContainer.tsx → CLAUDE.md requires custom project variants (primary, secondary, danger) for Button/ActionIcon; replace variant="subtle" on the add/delete action icons with the appropriate custom variant

  • ⚠️ File size guideline exceededGroupContainer.tsx (302 lines) and useDashboardContainers.tsx (306 lines) both slightly exceed the project's 300-line limit from CLAUDE.md; consider splitting each by ~10 lines (e.g., extract the tab-bar rendering from GroupContainer, or the tab CRUD from useDashboardContainers)

  • ⚠️ PR description mentions 'tab' container type and parentId field that don't appear in the actual diff → Update the PR description to match what's actually implemented (the enum only adds 'group', no parentId field exists)

  • ℹ️ handleGroupSelected in useTileSelection.ts creates a 'section' container, not a 'group' — this is consistent with the UI label "Group into Section" but the function name implies otherwise; no code change needed but worth a comment for future maintainers

@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

E2E Test Results

All tests passed • 91 passed • 3 skipped • 951s

Status Count
✅ Passed 91
❌ Failed 0
⚠️ Flaky 2
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 9d1a5c2 to 0d2b11f Compare March 23, 2026 20:56
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch 2 times, most recently from a7afc78 to fd8799e Compare March 23, 2026 21:14
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from fd8799e to 20a628e Compare March 23, 2026 21:37
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from d65d046 to 0fb0522 Compare March 23, 2026 21:47
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 0fb0522 to e38c98b Compare March 23, 2026 21:51
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from e38c98b to 74ee92a Compare March 23, 2026 21:56
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 74ee92a to 4aee30f Compare March 23, 2026 22:02
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 4aee30f to ae5981a Compare March 23, 2026 22:20
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from ae5981a to 82579ce Compare March 23, 2026 23:35
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 82579ce to 8d7be4f Compare March 23, 2026 23:45
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 8d7be4f to de53c17 Compare March 23, 2026 23:50
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from de53c17 to 39414b1 Compare March 23, 2026 23:58
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 39414b1 to 6ea1263 Compare March 24, 2026 00:40
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 6ea1263 to 1929e28 Compare March 24, 2026 00:53
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 1929e28 to aeaca9e Compare March 24, 2026 01:14
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from aeaca9e to 2682bfe Compare March 24, 2026 01:21
@alex-fedotyev alex-fedotyev force-pushed the feat/dashboard-dnd-organization branch from 2682bfe to 066d76d Compare March 24, 2026 02:41
section + group types. Groups always have tabs array (min 1 tab).
1 tab = plain group, 2+ tabs = tab bar. tabId on tiles for tab
assignment. activeTabId persisted (Grafana/Kibana pattern).
DashboardDndContext: sortable container reorder provider.
DashboardDndComponents: EmptyContainerPlaceholder with [+ Add] button
(fw=400 matching bottom Add), SortableSectionWrapper.
1 tab: plain header showing tabs[0].title, rename edits the tab.
2+ tabs: tab bar with hover-only x, inline +, double-click rename.
No separate container title — group identity IS the first tab.
Adding tab to 1-tab group adds second tab. Removing to 1 reverts.
Groups always created with 1 tab. Add Tab adds 2nd tab. Delete to 1
keeps tab. Header rename syncs tabs[0]. Always-confirm delete.
RGL-native positioning (x=0, y=0, auto-compact fills right then wraps).
Section empty state wired with onAddTile. Floating drag bar on hover.
Move dropdown: 1-tab group shows name directly, 2+ shows Group > Tab.
Delete confirmation always shown. Select-and-group with Cmd+G.
54 tests: group always has 1 tab, add tab creates 2nd, title syncs
from tabs[0], delete to 1 keeps tab, section reorder, tile grouping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: Enterprise-grade organization (sections, tabs, groups, drag-and-drop)

1 participant